package com.example.user_manage.service.impl;

import ch.qos.logback.core.util.StringUtil;
import com.example.user_manage.entity.Role;
import com.example.user_manage.entity.User;
import com.example.user_manage.dto.UserRequestDTO;
import com.example.user_manage.enums.ExceptionEnum;
import com.example.user_manage.exception.ServiceException;
import com.example.user_manage.mapper.RoleMapper;
import com.example.user_manage.mapper.TUserRoleMapper;
import com.example.user_manage.mapper.UserMapper;
import com.example.user_manage.service.UserService;
import com.example.user_manage.util.EntityOrDTOUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;

@Slf4j
@Service
@AllArgsConstructor
@Transactional
public class UserServiceImpl implements UserService {
    /**
     * 用户DAO操作对象
     */
    final private UserMapper userMapper;
    /**
     * 用户角色对应关系DAO操作对象
     */
    final private TUserRoleMapper tUserRoleMapper;
    private final RoleMapper roleMapper;

    /**
     * 通过登录账号查询用户
     * @param loginAct 登录账号
     * @return User用户对象
     */
    public User selectUserByLoginAct(String loginAct) throws ServiceException{
        log.info("账号查询:{}",loginAct);
        //检测登录账号是否为空？
        if (StringUtil.isNullOrEmpty(loginAct)) {
            //记录日志
            log.error("用户服务异常：用户账号为空字符串儿或null");
            //为空则抛出异常
            throw new ServiceException(ExceptionEnum.LOGIN_ACT_NULL);
        }else {
            User user = userMapper.selectUserByLoginAct(loginAct);
            log.info("返回查询结果");
            return user;
        }
    }

    /**
     * 增加新用户
     * @param userRequestDTO 用户数据传输对象
     */
    public void insertUser(UserRequestDTO userRequestDTO) throws ServiceException {
        log.info("开始创建用户");
        //验证用户传输对象（请求携带的）是否与数据库内数据冲突
        if(userRequestDTO == null){
            log.error("用户服务异常：传入的User为null");
            throw new ServiceException(ExceptionEnum.USER_NULL);

        }else if(userMapper.selectUserByLoginAct(userRequestDTO.getLoginAct()) != null){
            log.error("用户服务异常：该账号已被注册{}",userRequestDTO.getLoginAct());
            throw new ServiceException(ExceptionEnum.LOGIN_ACT_REPEAT);

        }else if(userMapper.selectUserByEmail(userRequestDTO.getEmail()) != null){
            log.error("用户服务异常：该邮箱已被注册{}",userRequestDTO.getEmail());
            throw new ServiceException(ExceptionEnum.EMAIL_REPEAT);
        }else {
            //将用户传输对象转换成用户对象
            User user = EntityOrDTOUtil.toUser(userRequestDTO);

            //对密码进行加密
            PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
            user.setPassword(passwordEncoder.encode(user.getPassword()));

            //记录现在的时间
            Date nowDate = new Date();
            user.setCreateTime(nowDate);//创造时间
            user.setEditTime(nowDate);//编辑时间
            log.info("将用户“{}”写入数据库",user.getName());
            userMapper.insert(user);
            log.info("创建成功");
        }
    }

    /**
     * 根据用户id修改用户数据
     * @param userRequestDTO 想要达到的用户对象修改效果
     */
    public void updateUserByUserId(UserRequestDTO userRequestDTO)throws ServiceException {
        log.info("开始修改用户信息");
        //验证号用户id是否为空字符串或null
        if(userRequestDTO ==null){
            log.error("修改用户信息失败：要修改的用户id号不能为空");
            throw new ServiceException(ExceptionEnum.USER_ID_NULL);

        }else if(userMapper.excludeIdSelectUserByLoginAct(userRequestDTO.getId()
                ,userRequestDTO.getLoginAct()) != null){
            log.error("修改用户信息失败：{}该账号已经存在",userRequestDTO.getLoginAct());
            throw new ServiceException(ExceptionEnum.LOGIN_ACT_REPEAT);

        } else if (userMapper.excludeIdSelectUserByEmail(userRequestDTO.getId()
                ,userRequestDTO.getEmail()) != null) {
            log.error("用户信息修改失败：{}该邮箱已被注册",userRequestDTO.getEmail());
            throw new ServiceException(ExceptionEnum.EMAIL_REPEAT);
        }
        //将用请求携带的用户数据传输对象转换成User用户对象
        User user = EntityOrDTOUtil.toUser(userRequestDTO);
        //修改编辑时间
        Date nowDate = new Date();
        user.setEditTime(nowDate);
        log.info("将新的用户数据写入数据库");
        userMapper.updateByPrimaryKeySelective(user);
        log.info("数据写入成功");
    }

    /**
     * 删除用户，通过用户id
     * @param id 用户id
     */
    public void deleteUserByUserId(Long id) throws ServiceException{
        log.info("删除用户开始");
        if(id==null){
            log.error("用户服务异常：用户id为null");
            throw new ServiceException(ExceptionEnum.USER_ID_NULL);
        }else {
            log.info("正在删除数据库用户数据，用户id为{}",id);
            //删除用户关联的角色对应关系
            tUserRoleMapper.deleteByUserId(id);
            //删除用户
            userMapper.deleteByPrimaryKey(id);
            log.info("删除成功");
        }
    }

    /**
     * 插入用户角色对应关秀
     * @param userId 用户id号
     * @param roleId 角色id号
     */
    public void insertUserRole(Long userId,Long roleId) throws ServiceException {
        log.info("开始新建用户角色对应关系");
        if(userId==null){
            log.error("传入的用户id不能为空");
            throw new ServiceException(ExceptionEnum.USER_ID_NULL);

        }else if(roleId==null){
            log.error("传入的角色id不能为空");
            throw new ServiceException(ExceptionEnum.ROLE_ID_NULL);

        }else if(tUserRoleMapper.selectByUserIdAndRoleId(userId,roleId) != null){
            log.error("该对应关系已经存在");
            throw new ServiceException(ExceptionEnum.USER_ROLE_REPEAT);

        }else {
            tUserRoleMapper.insertByUserIdRoleId(userId,roleId);
            log.info("用户角色对应关系注册成功");
        }
    }

    /**
     * 删除用户角色对应关系
     * @param userId 用户id号
     * @param roleId 角色id号
     */
    public void deleteUserRole(Long userId, Long roleId) throws ServiceException{
        log.info("删除用户角色对应关系开始");
        if(userId==null){
            log.error("删除用户角色对应关系时，用户id不能为空");
            throw new ServiceException(ExceptionEnum.USER_ID_NULL);

        }else if(roleId==null){
            log.error("删除用户角色对应关系时，角色id不能为空");
            throw new ServiceException(ExceptionEnum.ROLE_ID_NULL);

        }else if(tUserRoleMapper.selectByUserIdAndRoleId(userId,roleId) == null){
            log.error("你要删除的用户角色关系并不存在");
            throw new ServiceException(ExceptionEnum.USER_ROLE_NOT_FIND);

        }else {
            tUserRoleMapper.deleteByUserIdRoleId(userId,roleId);
            log.info("用户角色对应关系删除成功");
        }
    }

    /**
     * 查询用户角色列表，通过用户id
     * @param userId 用户id
     * @return 角色列表
     */
    public List<Role> selectRolesByUserId(Long userId){
        return roleMapper.selectRolesByUserId(userId);
    }

    /**
     * 查询所有角色id为roleId的用户
     * @param roleId 角色id
     * @param pageNum 当前所在页面
     * @param pageSize 页面展示的记录条数
     * @return 页面信息对象
     */
    public PageInfo<User> selectUsersByRoleId(Long roleId, int pageNum, int pageSize){
        if(roleId == 0 ){
            log.error("通过角色id查询用户时，角色Id不能为null");
            throw new ServiceException(ExceptionEnum.ROLE_ID_NULL);
        }

        log.info("开始查询，查询角色id为：{}的用户",roleId);
        //查询拥有该角色id的用户并返回
        PageHelper.startPage(pageNum, pageSize);
        List<User> users = userMapper.selectUsersByRoleId(roleId);
        return new PageInfo<>(users);
    }
}
